<?php

namespace App\ServicesNew\Impl;

use App\BO\Distributor\DistributorBO;
use App\BO\Distributor\Meta\BindRelationShip;
use App\BO\Distributor\Meta\UserDistributorRate;
use App\Entities\DistributorEntity;
use App\Entities\DistributorStatEntity;
use App\Entities\DistributorStatModel;
use App\Entities\OrderEntity;
use App\Entities\PaymentEntity;
use App\Entities\PaymentModel;
use App\Entities\QrcodeAdvertisingEntity;
use App\Entities\TransactionRecordEntity;
use App\Entities\TransactionRecordModel;
use App\ServicesNew\BaseSearchServiceTrait;
use App\ServicesNew\DistributorService;
use App\Utils\MoneyFormatUtil;
use App\VO\UserBalance\TransactionSearchInfo;
use Illuminate\Support\Facades\DB;

class DistributorServiceImpl implements DistributorService
{
    use BaseSearchServiceTrait;

    /**
     * @inheritDoc
     */
    public function getBindRelationShip(int $userId)
    {
        $bindRelationShip = new BindRelationShip();
        $bindRelationShip->setUserId($userId);

        // 一级
        $qrcodeAdvertisingEntity = QrcodeAdvertisingEntity::findByUserId($userId);
        if (is_null($qrcodeAdvertisingEntity)) {
            return $bindRelationShip;
        }

        $p = new UserDistributorRate();
        $p->setUserId($qrcodeAdvertisingEntity->getAgentid());
        $p->setRate(DistributorBO::getLevel1Rate());
        $bindRelationShip->setPUser($p);

        // 二级
        $qrcodeAdvertisingEntity = QrcodeAdvertisingEntity::findByUserId($p->getUserId());
        if (is_null($qrcodeAdvertisingEntity)) {
            return $bindRelationShip;
        }

        $pp = new UserDistributorRate();
        $pp->setUserId($qrcodeAdvertisingEntity->getAgentid());
        $pp->setRate(DistributorBO::getLevel2Rate());
        $bindRelationShip->setPpUser($pp);

        return $bindRelationShip;
    }

    /**
     * @inheritDoc
     */
    public function giveProfit(int $userId, PaymentEntity $paymentEntity)
    {
        if (!($paymentEntity->getOrderType() == PaymentModel::ORDER_TYPE_CONVERTIBLE_CARD)) {
            $this->giveFreezeProfit($userId, $paymentEntity);
            return;
        }

        $bindRelationShip = $this->getBindRelationShip($userId);
        $amount = $paymentEntity->getAmount();

        DB::beginTransaction();
        foreach ($bindRelationShip->getAllDistributors() as $distributor) {
            $this->addProfitRecord($amount, $distributor);
        }
        DB::commit();
    }

    /**
     * @inheritDoc
     */
    public function giveFreezeProfit(int $userId, PaymentEntity $paymentEntity)
    {
        $bindRelationShip = $this->getBindRelationShip($userId);
        $amount = $paymentEntity->getAmount();

        $orderEntity = OrderEntity::findByTradeNo($paymentEntity->getTradeNo());
        $orderId = $orderEntity->getId();

        DB::beginTransaction();
        foreach ($bindRelationShip->getAllDistributors() as $distributor) {
            $this->addFreezeProfitRecord($amount, $orderId, $distributor);
        }
        DB::commit();
    }

    /**
     * @inheritDoc
     */
    public function addFreezeProfitRecord(int $amount, int $orderId, UserDistributorRate $userDistributorRate)
    {
        $freezeAmount = MoneyFormatUtil::pennyToDollar($amount / 100 * $userDistributorRate->getRate());

        DB::beginTransaction();

        // 1. 修改总记录
        $distributorEntity = DistributorEntity::findOrCreateByUserId($userDistributorRate->getUserId());
        $distributorEntity->setFreezeBalance(
            MoneyFormatUtil::dollarAddDollar($freezeAmount, $distributorEntity->getFreezeBalance())
        );
        $distributorEntity->save();

        // 2.
        $distributorStatEntity = DistributorStatEntity::getNewInstance();
        $distributorStatEntity->setOrderId($orderId);
        $distributorStatEntity->setDistributorId($userDistributorRate->getUserId());
        $distributorStatEntity->setProfit($freezeAmount);
        $distributorStatEntity->setOrderTime(time());
        $distributorStatEntity->save();

        // 3. 增加详情数据
        $transactionRecordEntity = TransactionRecordEntity::getNewInstance();
        $transactionRecordEntity->setDistributorStateId($distributorStatEntity->getId());
        $transactionRecordEntity->setDisId($userDistributorRate->getUserId());
        $transactionRecordEntity->setMoney($freezeAmount);
        $transactionRecordEntity->setType(TransactionRecordModel::TRANSACTION_RECORD_TYPE_好友下单);
        $transactionRecordEntity->setIsFreeze(1);
        $transactionRecordEntity->save();

        DB::commit();
    }

    /**
     * @inheritDoc
     */
    public function addProfitRecord(int $amount, UserDistributorRate $userDistributorRate)
    {
        $profit = MoneyFormatUtil::pennyToDollar($amount / 100 * $userDistributorRate->getRate());

        DB::beginTransaction();

        // 1. 修改总记录
        $distributorEntity = DistributorEntity::findOrCreateByUserId($userDistributorRate->getUserId());
        $distributorEntity->setBalance(MoneyFormatUtil::dollarAddDollar($profit, $distributorEntity->getBalance()));
        $distributorEntity->setPreBalance(MoneyFormatUtil::dollarAddDollar($profit, $distributorEntity->getPreBalance()));
        $distributorEntity->save();

        // 2. 增加详情数据
        $transactionRecordEntity = TransactionRecordEntity::getNewInstance();
        $transactionRecordEntity->setDisId($userDistributorRate->getUserId());
        $transactionRecordEntity->setMoney($profit);
        $transactionRecordEntity->setType(TransactionRecordModel::TRANSACTION_RECORD_TYPE_好友下单);
        $transactionRecordEntity->save();

        DB::commit();
    }

    /**
     * @inheritDoc
     */
    public function confirm(PaymentEntity $paymentEntity)
    {
        $orderEntity = OrderEntity::findByTradeNo($paymentEntity->getTradeNo());
        $trades = TransactionRecordEntity::getByOrderId($orderEntity->getId());

        foreach ($trades as $trade) {
            $this->unfreeze($trade);
        }
    }

    /**
     * @inheritDoc
     */
    public function unfreeze(TransactionRecordEntity $transactionRecordEntity)
    {
        $money = $transactionRecordEntity->getMoney();

        $distributorEntity = DistributorEntity::findOrCreateByUserId($transactionRecordEntity->getUserId());

        // 1
        $distributorEntity->setBalance(MoneyFormatUtil::dollarAddDollar($money, $distributorEntity->getBalance()));
        $distributorEntity->setFreezeBalance(MoneyFormatUtil::dollarAddDollar($money * -1, $distributorEntity->getFreezeBalance()));
        $distributorEntity->setPreBalance(MoneyFormatUtil::dollarAddDollar($money, $distributorEntity->getPreBalance()));
        $distributorEntity->save();

        // 2
        $transactionRecordEntity->setIsFreeze(0);
        $transactionRecordEntity->save();

        // 3
        $distributorStatEntity = DistributorStatEntity::find($transactionRecordEntity->getDistributorStateId());
        $distributorStatEntity->setStatus(DistributorStatModel::DISTRIBUTOR_STATS_STATUS_已入余额);
        $distributorStatEntity->save();

    }

    /**
     * @inheritDoc
     */
    public function refund(PaymentEntity $paymentEntity)
    {
        $orderEntity = OrderEntity::findByTradeNo($paymentEntity->getTradeNo());
        $trades = TransactionRecordEntity::getByOrderId($orderEntity->getId());

        foreach ($trades as $trade) {
            $this->rollback($trade);
        }
    }

    /**
     * @inheritDoc
     */
    public function rollback(TransactionRecordEntity $transactionRecordEntity)
    {
        DB::beginTransaction();

        $distributorEntity = DistributorEntity::findOrCreateByUserId($transactionRecordEntity->getUserId());

        // 1
        $distributorEntity->setFreezeBalance(MoneyFormatUtil::dollarAddDollar($transactionRecordEntity->getMoney() * -1, $distributorEntity->getFreezeBalance()));
        $distributorEntity->save();

        // 2 增加一条回退记录
        $transactionRecordEntity->setIsFreeze(0);
        $transactionRecordEntity->save();

        $newInstance = TransactionRecordEntity::getNewInstance();
        $newInstance->setDistributorStateId($transactionRecordEntity->getDistributorStateId());
        $newInstance->setDisId($transactionRecordEntity->getDisId());
        $newInstance->setMoney($transactionRecordEntity->getMoney());
        $newInstance->setType(TransactionRecordModel::TRANSACTION_RECORD_TYPE_好友下单_取消);
        $newInstance->save();

        // 3
        $distributorStatEntity = DistributorStatEntity::find($transactionRecordEntity->getDistributorStateId());
        $distributorStatEntity->setStatus(DistributorStatModel::DISTRIBUTOR_STATS_STATUS_已取消);
        $distributorStatEntity->save();

        DB::commit();
    }

    /**
     * @inheritDoc
     */
    public function getTransactionRecord(TransactionSearchInfo $searchInfo)
    {
        return $this->getEntities(TransactionRecordEntity::class, TransactionRecordModel::class, $searchInfo);
    }

    /**
     * @inheritDoc
     */
    public function count(TransactionSearchInfo $searchInfo)
    {
        return $this->countNum(TransactionRecordModel::class, $searchInfo);
    }

    /**
     * @param TransactionSearchInfo $searchInfo
     * @return array
     */
    private function getSearchCondition(TransactionSearchInfo $searchInfo)
    {
        $condition = [];
        $userId = $searchInfo->getUserId();
        if (!empty($userId)) {
            $condition[] = ['dis_id', $userId];
        }
        return $condition;
    }
}
